package com.foodie.proxy.dynamicproxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 代理对象工厂
 * 工厂类的实现类只保留一个，提供方法返回特定类的代理对象(单例模式)
 */
public class ProxyFactory {
    //初始化类时初始化唯一对象
    private static ProxyFactory proxyFactory = new ProxyFactory();

    /**
     * 私有构造函数
     */
    private ProxyFactory() {
    }

    /**
     * 对外获取唯一工厂方法
     *
     * @return
     */
    public static ProxyFactory getInstance() {
        return proxyFactory;
    }

    /**
     * 使用JDK动态代理生成代理对象
     *
     * @param obj 目标对象
     * @return
     */
    public Object getJDKProxy(Object obj) {
        Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
            /**
             * @param proxy
             * @param method 当前被调用方法
             * @param args 当前被调用方法传入的参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object object = null;
                //功能增强
                System.out.println("收代理租房费300元。");
                //代理本职需要做的事(即调用代理类租房函数)
                object = method.invoke(obj, args);
                //功能增强
                System.out.println("客户信息卖了3毛。");
                return object;
            }
        });
        return proxy;

    }

    /**
     * 使用Cglib动态代理生成代理对象
     *
     * @param obj
     * @return
     */
    public Object getCglibProxy(Object obj) {
        Object proxy = Enhancer.create(obj.getClass(), new MethodInterceptor() {//参数1：委托对象的类  参数2：MethodInterceptor方法拦截器
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object object = null;
                //功能增强
                System.out.println("收代理租房费300元。");
                //代理本职需要做的事(即调用代理类租房函数)
                object = method.invoke(obj, objects);//参数1：委托对象 参数2：传入函数参数
                //功能增强
                System.out.println("客户信息卖了3毛。");
                return object;
            }
        });
        return proxy;
    }

}
/*
JDK动态代理：要求委托对象实现接口
Cglib动态代理：委托对象实现接口也可以
*/
